/*
 * Copyright (c) 2022. China Mobile (SuZhou) Software Technology Co.,Ltd. All rights reserved.
 * Lakehouse is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */

package com.chinamobile.cmss.lakehouse.core.client;

import com.chinamobile.cmss.lakehouse.common.kubernetes.NodeResource;

import java.io.InputStream;
import java.util.List;
import java.util.Optional;

import io.kubernetes.client.custom.V1Patch;
import io.kubernetes.client.openapi.ApiClient;
import io.kubernetes.client.openapi.ApiException;
import io.kubernetes.client.openapi.models.V1ClusterRoleBinding;
import io.kubernetes.client.openapi.models.V1ConfigMap;
import io.kubernetes.client.openapi.models.V1ConfigMapList;
import io.kubernetes.client.openapi.models.V1DeleteOptions;
import io.kubernetes.client.openapi.models.V1Deployment;
import io.kubernetes.client.openapi.models.V1DeploymentList;
import io.kubernetes.client.openapi.models.V1Namespace;
import io.kubernetes.client.openapi.models.V1NamespaceList;
import io.kubernetes.client.openapi.models.V1NodeList;
import io.kubernetes.client.openapi.models.V1Pod;
import io.kubernetes.client.openapi.models.V1PodList;
import io.kubernetes.client.openapi.models.V1Service;
import io.kubernetes.client.openapi.models.V1ServiceList;
import io.kubernetes.client.openapi.models.V1StatefulSet;
import io.kubernetes.client.openapi.models.V1StatefulSetList;
import io.kubernetes.client.openapi.models.V1Status;

public interface IKubernetesClient {

    /**
     * list Namespace by label selector
     *
     * @param labelSelector
     * @return
     * @throws ApiException
     */
    V1NamespaceList listNamespace(String labelSelector) throws ApiException;

    /**
     * list ConfigMap in namespace
     *
     * @param namespace name of namespace to list
     * @return
     * @throws ApiException
     */
    V1ConfigMapList listConfigMap(final String namespace) throws ApiException;

    /**
     * list Service in namespace
     *
     * @param namespace name of namespace to list
     * @return
     * @throws ApiException
     */
    V1ServiceList listService(final String namespace) throws ApiException;

    /**
     * list StatefulSet
     *
     * @param namespace the name of Namespace
     * @return
     * @throws ApiException
     */
    V1StatefulSetList listStatefulSet(String namespace) throws ApiException;

    /**
     * list Deployment
     *
     * @param namespace the name of Namespace
     * @return
     * @throws ApiException
     */
    V1DeploymentList listDeployment(String namespace) throws ApiException;

    /**
     * list all pods
     *
     * @return
     * @throws ApiException
     */
    V1PodList listPodForAllNamespaces() throws ApiException;

    /**
     * create Namespace in k8s
     *
     * @param namespace
     * @return
     * @throws ApiException
     */
    V1Namespace createNamespace(String namespace) throws ApiException;

    /**
     * create ClusterRoleBinding in k8s
     *
     * @param clusterRoleBinding
     * @return
     * @throws ApiException
     */
    V1ClusterRoleBinding createClusterRoleBinding(V1ClusterRoleBinding clusterRoleBinding)
        throws ApiException;

    /**
     * create ConfigMap in k8s
     *
     * @param namespace
     * @param configMap
     * @return
     * @throws ApiException
     */
    V1ConfigMap createConfigMap(String namespace, V1ConfigMap configMap) throws ApiException;

    /**
     * create Service in k8s
     *
     * @param namespace
     * @param service
     * @return
     * @throws ApiException
     */
    V1Service createService(String namespace, V1Service service) throws ApiException;

    /**
     * create StatefulSet in k8s
     *
     * @param namespace
     * @param statefulSet
     * @return
     * @throws ApiException
     */
    V1StatefulSet createStatefulSet(String namespace, V1StatefulSet statefulSet) throws ApiException;

    /**
     * create Deployment in k8s
     *
     * @param namespace
     * @param deployment
     * @return
     * @throws ApiException
     */
    V1Deployment createDeployment(String namespace, V1Deployment deployment) throws ApiException;

    /**
     * patch Deployment in k8s
     *
     * @param deploymentName
     * @param namespace
     * @param body
     * @return
     * @throws ApiException
     */
    V1Deployment patchDeployment(String deploymentName, String namespace, V1Patch body) throws ApiException;

    /**
     * patch StatefulSet in k8s
     *
     * @param statefulSetName
     * @param namespace
     * @param body
     * @throws ApiException
     */
    void patchStatefulSet(String statefulSetName, String namespace, V1Patch body) throws ApiException;

    /**
     * replace ConfigMap in k8s
     *
     * @param name
     * @param namespace
     * @param configMap
     * @return
     * @throws ApiException
     */
    V1ConfigMap replaceConfigMap(String name, String namespace, V1ConfigMap configMap)
        throws ApiException;

    /**
     * read ConfigMap in k8s
     *
     * @param name
     * @param namespace
     * @return
     * @throws ApiException
     */
    Optional<V1ConfigMap> readConfigMap(String name, String namespace) throws ApiException;

    /**
     * replace Service in k8s
     *
     * @param name
     * @param namespace
     * @param service
     * @return
     * @throws ApiException
     */
    V1Service replaceService(String name, String namespace, V1Service service) throws ApiException;

    /**
     * replace StatefulSet in k8s
     *
     * @param name
     * @param namespace
     * @param statefulSet
     * @return
     * @throws ApiException
     */
    V1StatefulSet replaceStatefulSet(String name, String namespace, V1StatefulSet statefulSet)
        throws ApiException;

    /**
     * replace Deployment in k8s
     *
     * @param name
     * @param namespace
     * @param deployment
     * @return
     * @throws ApiException
     */
    V1Deployment replaceDeployment(String name, String namespace, V1Deployment deployment)
        throws ApiException;

    /**
     * delete Namespace in k8s
     *
     * @param namespace
     * @param options
     * @return
     * @throws ApiException
     */
    V1Status deleteNamespace(String namespace, V1DeleteOptions options) throws ApiException;

    /**
     * delete ClusterRoleBinding in k8s
     *
     * @param crbName
     * @param options
     * @return
     * @throws ApiException
     */
    V1Status deleteClusterRoleBinding(String crbName, V1DeleteOptions options) throws ApiException;

    /**
     * delete ConfigMap in k8s
     *
     * @param namespace
     * @param configMapName
     * @param options
     * @return
     * @throws ApiException
     */
    V1Status deleteConfigMap(String namespace, String configMapName, V1DeleteOptions options)
        throws ApiException;

    /**
     * delete Service in k8s
     *
     * @param namespace
     * @param serviceName name of Service to delete
     * @param options
     * @return
     * @throws ApiException
     */
    V1Status deleteService(String namespace, String serviceName, V1DeleteOptions options)
        throws ApiException;

    /**
     * delete StatefulSet in k8s
     *
     * @param namespace
     * @param statefulSetName name of StatefulSet to delete
     * @param options
     * @return
     * @throws ApiException
     */
    V1Status deleteStatefulSet(String namespace, String statefulSetName, V1DeleteOptions options)
        throws ApiException;

    /**
     * delete Deployment in k8s
     *
     * @param namespace
     * @param deploymentName name of Deployment to delete
     * @param options
     * @return
     * @throws ApiException
     */
    V1Status deleteDeployment(String namespace, String deploymentName, V1DeleteOptions options)
        throws ApiException;

    /**
     * check Namespace exist
     *
     * @param namespace
     * @return
     * @throws ApiException
     */
    boolean existNamespace(String namespace) throws ApiException;

    /**
     * check clusterRoleBinding exist
     *
     * @param clusterRoleBinding
     * @return
     * @throws ApiException
     */
    boolean existClusterRoleBinding(String clusterRoleBinding) throws ApiException;

    /**
     * check configMap exist
     *
     * @param namespace name of namespace
     * @param configMap name of ConfigMap to check
     * @return
     * @throws ApiException
     */
    boolean existConfigMap(String namespace, String configMap) throws ApiException;

    /**
     * check service exist
     *
     * @param namespace
     * @param service
     * @return
     * @throws ApiException
     */
    boolean existService(String namespace, String service) throws ApiException;

    /**
     * check statefulSet exist
     *
     * @param namespace       name of namespace
     * @param statefulSetName name of StatefulSet to check
     * @return
     * @throws ApiException
     */
    boolean existStatefulSet(String namespace, String statefulSetName) throws ApiException;

    /**
     * check deployment exist
     *
     * @param namespace      name of namespace
     * @param deploymentName name of Deployment to check
     * @return
     * @throws ApiException
     */
    boolean existDeployment(String namespace, String deploymentName) throws ApiException;

    /**
     * check pod exist
     *
     * @param namespace name of namespace
     * @param podName   name of pod to check
     * @return
     * @throws ApiException
     */
    boolean existPod(String namespace, String podName);

    /**
     * read StatefulSet in k8s
     *
     * @param namespace
     * @param statefulSetName
     * @return
     */
    Optional<V1StatefulSet> readNamespacedStatefulSet(String namespace, String statefulSetName);

    /**
     * read Deployment in k8s
     *
     * @param namespace
     * @param deploymentName
     * @return
     */
    Optional<V1Deployment> readNamespacedDeployment(String namespace, String deploymentName);

    /**
     * read Pod in k8s
     *
     * @param namespace
     * @param podName
     * @return
     */
    Optional<V1Pod> readNamespacedPod(String namespace, String podName);

    /**
     * read pod log stream in k8s
     *
     * @param namespace
     * @param podName
     * @return
     */
    Optional<InputStream> readNamespacedPodLogStream(String namespace, String podName);

    /**
     * get kubernetes api client
     *
     * @return
     */
    ApiClient getApiClient();

    /**
     * list nodes
     *
     * @param labelSelector node selector
     * @return nodes with specified label
     * @throws ApiException
     */
    V1NodeList listNode(String labelSelector) throws ApiException;

    /**
     * get node resource list by specified label selector
     *
     * @param labelSelector label selector
     * @return
     * @throws ApiException
     */
    List<NodeResource> getNodeResources(String labelSelector) throws ApiException;

}
